#include "../header.h"

//静态 cid ; 
char bufs[128] = "";
char bufv[128] = "";
int len = 0 ;
void * pthread_fun(void * arg)
{
//----------------------------select 准备部分--------------------------------//
    //输入文件描述符集合
    fd_set rset = {0};
    //时间结构体
    struct timeval tm = {0};
    //有数据变化的文件描述符个数
    int count = 0 ;
    char bufh[128] = "";
//---------------------------------------------------------------------------//
    //cid是从主线程传过来的。   
    int pcid = *(int *)arg;
    //清空bufs
    bzero(bufs,sizeof(bufs));
    bzero(bufv,sizeof(bufv));
    while(strncmp(bufs,"quit",4))
    {
        //添加2个进来意味着，关心两个文件描述符。 键盘和 cid
        FD_SET(STDIN_FILENO,&rset);
        FD_SET(pcid,&rset);
        tm.tv_sec = 3;
        count = select(pcid + 1,&rset,NULL,NULL,&tm);
        if(count == 0 )
            printf("3秒钟之内没有文件描述符所对应的数据发生了变化:count = %d\n",count);
        else
            printf("有文件描述符变化:count = %d\n",count);

        //键盘有数据!
        if(FD_ISSET(STDIN_FILENO,&rset))
        {
            bzero(bufh,sizeof(bufh));
            printf("键盘有数据变化!\n");
            //从本地键盘接收到的数据  发送到对面去。
            read(STDIN_FILENO,bufh,sizeof(bufh));
            send(pcid,bufh,strlen(bufh),0);
        }

        //套接字文件描述符有数据变化
        if(FD_ISSET(pcid,&rset))
        {
            printf("客户端套接字有数据变化!\n");
            //cid 要传递过来
            bzero(bufs,sizeof(bufs));
            bzero(bufv,sizeof(bufv));
            //从对面发送多来的数据，我只看一看，打印到屏幕上看一看就行了。
            len = recv(pcid,bufs,sizeof(bufs),0);
            strncpy(bufv,bufs,strlen(bufs)-2);
            printf("客户端发送过来的数据是:%s len = %d\n",bufv,len);
    
        }

        //本代码只关心  pcid
        //没关心键盘

    }
    //线程退出 - cid关闭是不是一件事？
    shutdown(pcid,SHUT_RDWR);
    pcid = -1; 
    //线程退出
    pthread_exit((void *)0);
}

//多用户登录 - 并发服务器 - 线程方法
int main(int argc, char const *argv[])
{
    if(argc < 3)
    {
        perror("usage:./server ip port\n");
        return -1;
    }

    //.建立套接字
    int sid = socket(AF_INET,SOCK_STREAM,0);
    printf("sid = %d\n",sid);

    //实际地址结构体
    struct sockaddr_in saddr = {0};
    saddr.sin_family = AF_INET;
    saddr.sin_addr.s_addr = inet_addr(argv[1]);    
    saddr.sin_port = htons(atoi(argv[2]));
    if(bind(sid,(struct sockaddr*)&saddr,sizeof(saddr))<0)
    {
        perror("bind error\n");
        return -2;
    }
    printf("bind successful\n");

    //3.监听
    listen(sid,10);

    //4.循环连接
    char bufs[128] = "";
    int len = 0 ;
    pthread_t tid = 0 ;
    //只要初始化一次，在全局数据区
    static int cid = -1;
    while (1)
    {   //主线程。  链接。
        cid = accept(sid,NULL,NULL);
        if(cid != -1)
        {   
            //把线程设定成分离属性 - 线程执行完毕以后，自动释放占用的空间。
            pthread_create(&tid,NULL,pthread_fun,&cid);
            pthread_detach(tid);
            printf("有新用户登录 cid = %d\n",cid);
        }
       
    }
    return 0;
    
}
